﻿/*using Android.App;
using Android.Content;
using Android.Media;
using AndroidX.Core.App;
using InteractiveMusicPlayerMobile.控件与界面;
using NAudio.Vorbis;
using NAudio.Wave;
using NVorbis;
using System.Diagnostics;
using System.Security.Cryptography.X509Certificates;
using 交互音乐播放器.中间件;
using 交互音乐播放器.音频逻辑;
using static InteractiveMusicPlayerMobile.文件浏览器;

namespace InteractiveMusicPlayerMobile.安卓平台.辅助类
{
    [Service]
    public class 音频播放 : Service
    {
        private string NOTIFICATION_CHANNEL_ID = "1000";
        private int NOTIFICATION_ID = 1;
        private string NOTIFICATION_CHANNEL_NAME = "notification";
        public static 音频播放 运行时 { get; set; }
        public static object 锁定 { get; set; } = new object();
        public static bool 已析构 { get; set; } = true;
        public static Intent 服务 { get; set; }
        Dictionary<string, AudioTrack> 音频轨集;
        Dictionary<string, IWaveProvider> 读取器集;
        Dictionary<string, VorbisWaveReader> 文件流集;
        
        文件与文件夹 音频信息;
        public string 当前音频轨 = "当前流";
        public string 当前读取器;
        public bool 播放 { get; set; }
        int 最小缓冲区 = 0;
        public static int 设定位置 { get; set; } = -1;
        public static bool 不实际读取距离 { get; set; } = true;
        public Dictionary<string, WaveStream> 已载文件组 { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }

        public 音频播放()
        {
            new Thread(() =>
            {
                while (true)
                {
                    if (音频轨集 != null && 音频轨集.Values.FirstOrDefault()!=null && 音频轨集.FirstOrDefault().Value.PlayState != PlayState.Playing)
                    {
                        Debug.WriteLine("未播放已设置为析构");
                        已析构 = true;
                        Thread.Sleep(1500);
                        continue;
                    }
                    Debug.WriteLine("播放中");
                    Thread.Sleep(1500);
                }

            }).Start();
        }
        public static 音频播放 创建实例()
        {
            if (运行时 == null)
            {
                运行时 = new 音频播放();
            }
            return 运行时;
        }
        #region 服务代码
        public override void OnCreate()
        {
            base.OnCreate();
        }


        public override Android.OS.IBinder OnBind(Intent intent)
        {
            return null;
        }
        private void startForegroundService()
        {
            var notifcationManager = GetSystemService(Context.NotificationService) as NotificationManager;

            if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O)
            {
                createNotificationChannel(notifcationManager);
            }

            var notification = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);
            notification.SetAutoCancel(false);
            notification.SetOngoing(true);
            notification.SetSmallIcon(Resource.Mipmap.appicon);
            notification.SetContentTitle("交互音乐播放器 2");
            notification.SetContentText("正在后台循环播放音乐");
            StartForeground(NOTIFICATION_ID, notification.Build());
        }
        private void createNotificationChannel(NotificationManager notificationMnaManager)
        {
            var channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_NAME,
            NotificationImportance.Low);
            notificationMnaManager.CreateNotificationChannel(channel);
        }
        public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
        {
            startForegroundService();
            return StartCommandResult.NotSticky;
        }

        #endregion



        public static void 播放文件(文件与文件夹 音频信息, 播放信息 播放信息, (List<IWaveProvider> 读取器, List<VorbisWaveReader> 文件流) 文件信息)
        {

            音频播放 当前实例 = 音频播放.创建实例();
            运行时.音频信息 = 音频信息;
            //读取文件所有信息
            运行时.读取器集 = new Dictionary<string, IWaveProvider>();
            for (int i = 0; i < 文件信息.读取器.Count; i++)
            {
                
                运行时.读取器集.Add(音频信息.子文件标记[i], 文件信息.读取器[i]);
            }
            运行时.文件流集 = new Dictionary<string, VorbisWaveReader>();
            for (int i = 0; i < 文件信息.读取器.Count; i++)
            {
                运行时.文件流集.Add(音频信息.子文件标记[i], 文件信息.文件流[i]);
            }
            //创建播放实例
            if (安卓平台.辅助类.音频播放.运行时 != null)
            {
                Debug.WriteLine("找运行的实例，已先停止");
                安卓平台.辅助类.音频播放.运行时.停止();
            }

            //服务启动相关
            if (!播放信息.运行时.服务已启动)
            {
                播放信息.运行时.服务已启动 = true;
                Android.Content.Intent intent = new Android.Content.Intent(Android.App.Application.Context, typeof(音频播放));
                音频播放.服务 = intent;
                Android.App.Application.Context.StartForegroundService(intent);
            }

            当前实例.循环播放(运行时.读取器集.FirstOrDefault().Value, 文件信息.文件流.FirstOrDefault(),
            文件信息.读取器.FirstOrDefault().WaveFormat.SampleRate, 文件信息.读取器.FirstOrDefault().WaveFormat.Channels);

        }

        public void 循环播放(IWaveProvider 读取器, VorbisWaveReader 文件流, int 采样率, int 声道数)
        {
            while (!已析构) { int 重试次数 = 10; while (重试次数 > 0) { Debug.WriteLine($"等待上次播放析构，剩余{重试次数}次"); Thread.Sleep(15); 重试次数--;  } 已析构 = !已析构; }
            Debug.WriteLine("已进入播放逻辑");
            当前音频轨 = "当前流";
            当前读取器 = 音频信息.子文件标记.FirstOrDefault();
            this.文件流集[当前读取器] = 文件流;
            this.读取器集[当前读取器] = 读取器;
            播放 = true;
            //获取最低缓冲区
            测算最小缓冲区(采样率);
            音频轨集 = new Dictionary<string, AudioTrack>();
            音频轨集.Add(当前音频轨, new AudioTrack(Android.Media.Stream.Music, 采样率, ChannelConfiguration.Stereo, Android.Media.Encoding.Pcm16bit, 最小缓冲区, AudioTrackMode.Stream));
            Task.Run(() =>
            {
                OnCreate();
                循环读取();
            });
            音频轨集[当前音频轨].Play();


        }

        private void 测算最小缓冲区(int 采样率)
        {
            最小缓冲区 = AudioTrack.GetMinBufferSize(采样率, ChannelOut.Stereo, Android.Media.Encoding.Pcm16bit) ;
            if (文件流集.Count == 1) { 最小缓冲区 *= 2; return; }
            //寻找出本音频轨中，音频的最大大小，进行算法优化
            long 当前最大值 = 0;
            foreach (var 文件流 in 文件流集.Values)
            {
                if (文件流.Length > 当前最大值) { 当前最大值 = 文件流.Length; }
            }
            var 倍率 = (int)(当前最大值 / (long)4832348);
            if (倍率 < 2) { 倍率 = 2; }
            Console.WriteLine($"倍率为{倍率}");
            最小缓冲区 *= 倍率;
           
        }

        public void 恢复播放()
        {
            if (音频轨集[当前音频轨] == null || 文件流集[当前读取器] == null)
            {
                return;
            }
            播放 = true;

            音频轨集[当前音频轨].Play();
            Task.Run(() => { 循环读取(); });

        }
        public void 暂停()
        {
            if (音频轨集[当前音频轨] == null || 文件流集[当前读取器] == null)
            {
                return;
            }
            播放 = false;
            音频轨集[当前音频轨].Pause();
        }

        public void 停止()
        {
            播放 = false;
        }

        public void 设置进度(double 百分比)
        {
            var 总长度 = 文件流集[当前读取器].Length;
            Debug.WriteLine($"移动到 {百分比} -> {(int)(总长度 * (百分比 * 0.01))}");
            设定位置 = (int)(总长度 * (百分比 * 0.01));
        }

        private void 循环读取()
        {
            lock (锁定)
            {


                int 当前位置 = 0;
                int 上次读取大小 = 0;
                long 上次位置 = 0;
                long 实际读取距离 = -1;
                已析构 = false;
                while (播放)
                {

                    当前位置 = 0;
                    byte[] 缓冲区 = new byte[最小缓冲区];
                    手动切换位置();
                    Debug.WriteLine($"{文件流集[当前读取器].Position}/{文件流集[当前读取器].Length} + {上次读取大小 * 2}<上次实读：+{实际读取距离}> ({文件流集[当前读取器].Length - 文件流集[当前读取器].Position}) < {最小缓冲区 * 2}");
                    播放信息处理();
                    //前面已经读了足量的数据了，不可以再替换新的数据
                    if (文件流集[当前读取器].Length - 文件流集[当前读取器].Position <= 最小缓冲区*2)
                    {

                        Debug.WriteLine($"已修改缓冲");
                        Debug.WriteLine($"读取了剩下的{(int)(文件流集[当前读取器].Length - 文件流集[当前读取器].Position) / 2}");
                        var 剩余需读取大小 = (int)(文件流集[当前读取器].Length - 文件流集[当前读取器].Position);
                        读取器集[当前读取器].Read(缓冲区, 0, 剩余需读取大小 / 2);

                        当前位置 += 音频轨集[当前音频轨].Write(缓冲区, 0, 剩余需读取大小 / 2);

                        实际读取距离 = 文件流集[当前读取器].Position - 上次位置;
                        上次位置 = 文件流集[当前读取器].Position;
                        上次读取大小 = 当前位置;

                        更换流(ref 当前位置, out 上次读取大小, ref 上次位置, out 实际读取距离, 缓冲区);
                        continue;
                    }
                    读取器集[当前读取器].Read(缓冲区, 0, 最小缓冲区);
                    当前位置 += 音频轨集[当前音频轨].Write(缓冲区, 0, 最小缓冲区);
                    上次读取大小 = 当前位置;
                    实际读取距离 = 文件流集[当前读取器].Position - 上次位置;
                    上次位置 = 文件流集[当前读取器].Position;
                }
                已析构 = true;
            }
        }

        private void 手动切换位置()
        {
            if (音频播放.设定位置 != -1)
            {
                if (文件流集[当前读取器].Length - 音频播放.设定位置 <= 最小缓冲区*2)
                {
                    通知与日志.向当前页弹窗("您设置的目标播放位置，已不足以处理切换", "无法设置位置");
                    音频播放.设定位置 = -1;
                }
                else
                {
                    var 补数 = 音频播放.设定位置 % 8;//块对齐
                    文件流集[当前读取器].Position = 音频播放.设定位置 + 补数;
                    音频播放.设定位置 = -1;
                }
            }
        }

        private void 更换流(ref int 当前位置, out int 上次读取大小, ref long 上次位置, out long 实际读取距离, byte[] 缓冲区)
        {
            var 当前音频ID = 音频信息.子文件标记.IndexOf(当前读取器);
            if (当前音频ID != 音频信息.子文件标记.Count - 1) // 当前音频不是最后一个
            {
                当前读取器 = 音频信息.子文件标记[当前音频ID + 1]; 
            }
            else
            {
                文件流集[当前读取器].Position = 0;
            }
            Debug.WriteLine($"已读了：{当前位置 * 2}/{最小缓冲区*2} 空闲区剩余：{最小缓冲区 * 2 - (当前位置 * 2) } 需要填充：{(最小缓冲区 - 当前位置)*2}/{最小缓冲区*2}");
            读取器集[当前读取器].Read(缓冲区, 当前位置, (最小缓冲区 - 当前位置));
            当前位置 += 音频轨集[当前音频轨].Write(缓冲区, 当前位置, (最小缓冲区 - 当前位置));//读的时候已乘二
            实际读取距离 = 文件流集[当前读取器].Position - 上次位置;
            上次位置 = 文件流集[当前读取器].Position;
            上次读取大小 = 当前位置;
        }

        private void 播放信息处理()
        {
            控件与界面.播放信息.运行时.总时间 = $"{文件流集[当前读取器].TotalTime.ToString(@"mm\:ss")}";
            控件与界面.播放信息.运行时.已播时间 = $"{文件流集[当前读取器].CurrentTime.ToString(@"mm\:ss")}";
            控件与界面.播放信息.运行时.时间百分比 = ((int)System.Math.Round(((float)文件流集[当前读取器].Position / (float)文件流集[当前读取器].Length) * 100, 0));
            控件与界面.播放信息.运行时.音频章节名 = 当前读取器;

        }

        public void 使用效果(byte[] 音频缓冲区, int 偏移值, int 读取大小, string 流别名)
        {
            throw new NotImplementedException();
        }

        public int 内部_取得播放数据(byte[] 音频缓冲区, int 偏移值, int 读取大小, string 流别名)
        {
            throw new NotImplementedException();
        }

        public (bool 是否继续处理, int 已处理字节) 内部_处理CUE点逻辑(byte[] 音频缓冲区, int 偏移值, int 读取大小, string 流别名)
        {
            throw new NotImplementedException();
        }

        public void 内部_更新播放状态(int 剩余读取字节量, string 流别名)
        {
            throw new NotImplementedException();
        }

        public bool 命令_停止(string 播放流别名)
        {
            throw new NotImplementedException();
        }

        public bool 命令_停止所有()
        {
            throw new NotImplementedException();
        }

        public bool 命令_全部重定位(double 位置百分比)
        {
            throw new NotImplementedException();
        }

        public bool 命令_加载文件(string 文件路径, string 文件别名)
        {
            throw new NotImplementedException();
        }

        public bool 命令_播放音乐(string 播放流名称, string 文件别名)
        {
            throw new NotImplementedException();
        }

        public int 命令_新建播放流(string 流别名, int 流编号)
        {
            throw new NotImplementedException();
        }

        public bool 命令_暂停(string 播放流别名)
        {
            throw new NotImplementedException();
        }

        public bool 命令_暂停所有()
        {
            throw new NotImplementedException();
        }

        public bool 命令_更换文件(string 文件别名, string 流别名, int 起始偏移)
        {
            throw new NotImplementedException();
        }

        public void 命令_添加文件属性信息(string 文件别名, string 文件路径)
        {
            throw new NotImplementedException();
        }

        public void 命令_添加文件节拍信息(string 文件别名, float BPM, long 文件大小, TimeSpan 播放总时长)
        {
            throw new NotImplementedException();
        }

        public bool 命令_继续所有()
        {
            throw new NotImplementedException();
        }

        public bool 命令_重定位(long 字节位置, string 文件别名)
        {
            throw new NotImplementedException();
        }

        public bool 已载文件组加入文件(string 文件别名, string 文件路径, WaveStream 文件流)
        {
            throw new NotImplementedException();
        }

        public void 本段落读取完毕(string 流别名)
        {
            throw new NotImplementedException();
        }
    }
}
*/